﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using VMExplorer.Win32;

namespace VMExplorer.MemoryObjects
{
  /// <summary>
  /// File mapping in process' address space
  /// </summary>
  class SectionObject : GenericMemoryObject
  {
    #region Construction

    private SectionObject (SafeProcessHandle hProcess, MemoryAddress baseAddress, string path)
      : base(hProcess, baseAddress, Path.GetFileName(path), RegionUsage.Mappings)
		{
      FilePath = path;
		}

    #endregion
    #region Scan rule

    public static void InstallScanRule (Scanner scan)
    {
      scan.NextRegion += delegate (object sender, Scanner.NextRegionEventArgs e)
      {
        if (e.Handled) return;

        //if (e.Range.Type != Native.PAGE_TYPE.MEM_MAPPED) return;
        if (e.Range.Start != e.Range.Base) return;

        if (e.ProcessHandle.IsInvalid) return;

        StringBuilder lpFilename = new StringBuilder (1024);
        if (Native.GetMappedFileName (e.ProcessHandle, e.Range.Start, lpFilename, 1024) == 0) return;

        string filename = lpFilename.ToString ();

        foreach (string drivePath in Environment.GetLogicalDrives ())
        {
          string drive = drivePath.Substring (0, 2);
          StringBuilder lpTargetPath = new StringBuilder (1024);

          if (Native.QueryDosDevice (drive, lpTargetPath, 1024) != 0)
          {
            string targetPath = lpTargetPath.ToString ();

            if (filename.StartsWith (targetPath))
            {
              filename = filename.Replace (targetPath, drive);
              break;
            }
          }
        } 

        e.MemObjects.Add (new SectionObject (e.ProcessHandle, e.Range.Start, filename));
        e.Handled = true;
      };
    }

    #endregion
    #region Public Properties

    public string FilePath { get; private set; }

    #endregion
  }
}
